package com.huangge1199.common.util;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.huangge1199.common.ex.BaseException;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: huang
 * @Description excel处理工具
 * @Date: 2021-01-02 14:20
 */
@Component
public class ExcelDeal {

    private static ExcelDeal excelDeal;

    private ExcelDeal() {
        errorBl = false;
        errorStr = new StringBuilder();
        errorNum = 0;
    }

    public static ExcelDeal getInstance() {
        if (excelDeal == null) {
            excelDeal = new ExcelDeal();
        }
        return excelDeal;
    }

    /**
     * 是否出错
     */
    private boolean errorBl;
    /**
     * 错误信息
     */
    private StringBuilder errorStr;
    /**
     * 错误数量
     */
    private int errorNum;

    /**
     * excel导入
     *
     * @param dataList 需要数据的字段名
     * @param file     excel 文件
     * @return 需要字段的数据列表
     */
    public List<Map<String, String>> excelIn(List<Object> dataList, MultipartFile file) throws BaseException {
        errorBl = false;
        errorStr = new StringBuilder();
        errorNum = 0;
        List<Map<String, String>> result = new ArrayList<>(dataList.size());

        try {
            InputStream inputStream = file.getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream);

            List<Object> readHeader = reader.readRow(0);

            if (dataList.isEmpty()) {
                dataList = readHeader;
            }

            Map<String, Integer> dataIndex = headIndex(dataList, readHeader);

            if (errorBl) {
                return null;
            }

            int rowNum = reader.getRowCount();
            for (int i = 1; i < rowNum; i++) {
                List<Object> rowDataList = reader.readRow(i);
                if (rowDataList == null || rowDataList.isEmpty()) {
                    continue;
                }
                Map<String, String> map = new HashMap<>(dataList.size());
                for (Object data : dataList) {
                    map.put(data.toString(), rowDataList.get(dataIndex.get(data.toString())).toString());
                }
                result.add(map);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * excel导出
     * @param dataList 导出数据
     * @param response 响应
     * @throws IOException 异常
     */
    public void excelOut(List<Map<String,String>> dataList, HttpServletResponse response) throws IOException {
        ExcelWriter writer = ExcelUtil.getWriter(true);
        writer.write(dataList);
        writer.autoSizeColumnAll();
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition", "attachment;filename=test.xlsx");
        writer.flush(response.getOutputStream());
        writer.close();
    }

    /**
     * 查询出所有字段的所在列
     *
     * @param dataList       所有字段列表
     * @param readHeaderList 读取的头字段
     * @return 所有字段的所在列Map
     */
    private Map<String, Integer> headIndex(List<Object> dataList, List<Object> readHeaderList) throws BaseException {
        Map<String, Integer> indexMap = new HashMap<>(dataList.size());

        for (Object name : dataList) {
            if (readHeaderList.contains(name) && readHeaderList.indexOf(name) == readHeaderList.lastIndexOf(name)) {
                if (errorBl) {
                    continue;
                } else {
                    indexMap.put(name.toString(), readHeaderList.indexOf(name));
                }
            } else {
                errorBl = true;
                errorNum++;
                errorStr.append("\t").append(name).append("的列数不唯一或者没有").append(name).append("列,");
            }
            errorStr.append("请修改后再上传");
        }
        if (errorBl) {
            throw new BaseException(errorStr.toString());
        }
        return indexMap;
    }
}
